package com.gonsin.ta.logic.parse.condition;

import com.gonsin.ta.logic.enums.ComponentTypeEnum;
import com.gonsin.ta.logic.exceptions.TaException;
import com.gonsin.ta.logic.parse.serialize.TaSerializable;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;

public abstract class Condition implements Executable, TaSerializable {
    /**
     * 流程脚本的唯一标识
     */
    private String conditionId;

    {
        conditionId = RandomStringUtils.random(16, true, true).toUpperCase();
    }

    /**
     * 组件类型
     */
    public ComponentTypeEnum getComponentType(){
        return ComponentTypeEnum.CONDITION;
    }


    /**
     * 处理THIS关键词
     */
    public void handleThis(Map<String, Object> expressContext){
        List<FutureCondition> futureConditions = searchFutureConditions();
        if(!CollectionUtils.isEmpty(futureConditions)){
            for(FutureCondition c : futureConditions){
                String conditionName = c.getConditionName();
                Object condition = expressContext.get(conditionName);
                if(condition != null && condition instanceof Condition){
                    c.setFutureExecutable((Condition) condition);
                } else {
                    throw new TaException("找不到 【{}】方法", conditionName);
                }
            }
        }
    }


    /**
     * 搜索THIS关键词
     */
    public abstract List<FutureCondition> searchFutureConditions();


    public String getConditionId() {
        return conditionId;
    }

    public void setConditionId(String conditionId) {
        this.conditionId = conditionId;
    }


    /**
     * 从数据库中反序列化之后，需要回复嵌套方法
     * @param stack
     */
    public boolean handleStack(Map<String, Executable> stack) {
        boolean finished = true;
        List<FutureCondition> futureConditions = searchFutureConditions();
        if(!CollectionUtils.isEmpty(futureConditions)){
            for(FutureCondition c : futureConditions){
                if(c.getFutureExecutable() == null){
                    Condition found = (Condition) stack.get(c.getConditionId());
                    if(found != null ){
                        c.setFutureExecutable(found);
                        continue;
                    }
                    finished = false;
                }
            }
        }

        return finished;
    }
}
